#!/usr/bin/perl -w
# Copyright (c) 2011 Dmitry Streltsov. All rights reserved. This program is free
# software; you can redistribute it and/or modify it under the same terms as
# Perl itself.

# pragmas
use strict;
use utf8;

# modules
use Gtk2 -init;
use Gtk2::GladeXML;
use Glib qw(TRUE FALSE);
use Data::Dumper;

# DEBUG constant
use constant DEBUG => 1; 
#use constant DEBUG => undef;

#
our $SOURCE_FILE;
our $VERSION;
our $CONFIG_FILE;

our @pages;
our @headersFact;
our @headersPlaned;
our %DATASET_FACT_EXP_ARTS;
our %DATASET_PLANED_EXP_ARTS;

require './Libs/config.pm';
require './Libs/auxillary.pm';

# Configure Data::Dumper Module
$Data::Dumper::Indent = 0;
$Data::Dumper::Useqq = 1;
$Data::Dumper::Purity = 1;
                
# Define Planung - dataset
my %DATASET = (
                'date' => undef,
                'incRub' => undef,
                'incCom' => undef,
                'plExp' => undef,
                'plCom' => undef,
                'plTotal' => undef,
                'plFood' => undef,
                'plMisha' => undef,
                'plBenzin' => undef,
                'plFoodWork' => undef,
                'plProezd' => undef,
                'plKvarplata' => undef,
                'plProchee' => undef,
                'plProcheeCom' => undef,
                'plPivo' => undef,
                'plPodarki' => undef,
                'plCreditS' => undef,
                'plCreditR' => undef,
                'plCreditRF' => undef,
                'plMobile' => undef,
                'plInternet' => undef,
                'plLekarstva' => undef,
                'plMBox' => undef,
                'isExp' => undef,
                'isCom' => undef,
                'isTotal' => undef,
                'isFood' => undef,
                'isMisha' => undef,
                'isBenzin' => undef,
                'isFoodWork' => undef,
                'isProezd' => undef,
                'isKvarplata' => undef,
                'isProchee' => undef,
                'isProcheeCom' => undef,
                'isPivo' => undef,
                'isPodarki' => undef,
                'isCreditS' => undef,
                'isCreditR' => undef,
                'isCreditRF' => undef,
                'isMobile' => undef,
                'isInternet' => undef,
                'isLekarstva' => undef,
                'isCCard' => undef,
                'isMBox' => undef,
                'isKidCard' => undef
        );

my @DATASET_ELEMENTS = qw (date incRub incCom plExp plCom plTotal plFood plMisha plBenzin plFoodWork plProezd plKvarplata plProchee 
      plProcheeCom plPivo plPodarki plCreditS plCreditR plCreditRF plMobile plInternet plLekarstva plMBox isExp isCom isTotal 
      isFood isMisha isBenzin isFoodWork isProezd isKvarplata isProchee isProcheeCom isPivo isPodarki isCreditS isCreditR 
      isCreditRF isMobile isInternet isLekarstva isCCard isMBox isKidCard);

my %DATASET_FACT;         
my @DATASET_KEYS_FACT = qw (date incRub incCom isExp isCom isTotal isCCard isMBox);

my %DATASET_PLANED;
my @DATASET_KEYS_PLANED = qw (date incRub incCom plExp plCom plTotal plMBox);
        
my ( $date, $incRub,    $incCom, $plExp, $plCom, $plTotal, $plMBox,     $isExp, $isCom, $isTotal,
                $isCCard, $isMBox, $isKidCard, $isFood, $isMisha, $isBenzin, $isFoodWork, $isProezd, $isKvarplata,
                $isProchee,     $isProcheeCom, $isPivo, $isPodarki,     $isCreditS,     $isCreditR,     $isCreditRF, $isMobile,
                $isInternet, $isLekarstva, $plFood,     $plMisha, $plBenzin, $plFoodWork, $plProezd, $plKvarplata,
                $plProchee,     $plProcheeCom, $plPivo, $plPodarki,     $plCreditS,     $plCreditR,     $plCreditRF, $plMobile,
                $plInternet, $plLekarstva);
                
                
# Reading configuration file
# {{{
my @incomeArts;
my %expArts;

{
	open my $f_config, "<", $CONFIG_FILE or die "Cannot open ".$CONFIG_FILE." file: $!";
	binmode $f_config,":utf8";
	my $parent;

	while (<$f_config>) {
			# Read income arts
			push (@incomeArts, $+{artInc}) if (/incomeArt_[0-9](\s*)=(\s*)\'(?<artInc>.+)\';/);
			
			# Read parents (expense) and theirs children for TreeView
			if (/(?<PAR_KEY>expParent_[0-9])(\s*)=(\s*)\'(?<PAR_VAL>.+)\';/) {
					$parent = $+{PAR_VAL};
					# vivification >>> $expArts{$parent} = [ ];
			}
			elsif (/(?<CHLD_KEY>expParent_[0-9]::Child_[0-9])(\s*)=(\s*)\'(?<CHLD_VAL>.+)\';/) {
					die 'Parent is not defined!' unless defined $parent;
					push @{ $expArts{$parent} }, $+{CHLD_VAL};
			}
	}
}
# }}}

# Define row colors of main table
# {{{
my $header_color = Gtk2::Gdk::Color->parse("#CCFFCC");
my $row_color = Gtk2::Gdk::Color->parse("#DDFFDD");
my $odd_color = Gtk2::Gdk::Color->parse("#FFCC66");
my $even_color = Gtk2::Gdk::Color->parse("#CCFF99");
my $black = Gtk2::Gdk::Color->parse("#000000");
my $red = Gtk2::Gdk::Color->parse("#FFCCCC");
# }}}

my $font_desc_h = Gtk2::Pango::FontDescription->from_string ("Times New Roman 10");

# Glade XML
my $plMainWinXML = Gtk2::GladeXML->new('Planung_MainWin.glade');
$plMainWinXML->signal_autoconnect_from_package('main');
my $main_window = $plMainWinXML->get_widget('window');

# Show main window title "Planung $VERSION"
$main_window->set_title("Planung v".$VERSION);

# Creating the main page holder
my $hboxCenter = $plMainWinXML->get_widget('hboxCenter');
my $pgHolder = Gtk2::Notebook->new;

# Scrolled Window on Page "Fact"
my $scwin_fact = Gtk2::ScrolledWindow->new();
$scwin_fact->set_policy('automatic', 'automatic');
my $rows = 31;
my $cols = scalar @headersFact;
my $table_fact = Gtk2::Table->new($rows,$cols);

# Scrolled Window on Page "Planed"
my $scwin_plan = Gtk2::ScrolledWindow->new();
$scwin_plan->set_policy('automatic', 'automatic');
$cols = scalar @headersPlaned;
my $table_plan = Gtk2::Table->new($rows,$cols);

# Pages 
$pgHolder->append_page($scwin_fact, Gtk2::Label->new($pages[0]));
$pgHolder->append_page($scwin_plan, Gtk2::Label->new($pages[1]));
$pgHolder->append_page(Gtk2::Label->new($pages[2]), Gtk2::Label->new($pages[2]));
$pgHolder->append_page(Gtk2::Label->new($pages[3]), Gtk2::Label->new($pages[3]));

# Call building a table when the page changed
$pgHolder->signal_connect_after( 'switch-page', \&build_main_table);

$hboxCenter->pack_start($pgHolder, TRUE, TRUE, 4);
#END: creating the main page holder

$main_window->show_all(); 
Gtk2->main;
  
######### Subroutines: GLADE-handlers
# On Main Window Show
# {{{
sub mainWin_onShow {
   #set current month
   my $cbMonth = $plMainWinXML->get_widget('cbMonth');
   $cbMonth->set_active(getDataPart('MONTH'));     
   
   #set current year
   my $cbYear = $plMainWinXML->get_widget('cbYear');
   $cbYear->set_active(getDataPart('YEAR')-2009);  
}
# }}}

# On Button "Next Month >>"
# {{{
sub nextMonth_onClick {
   my $cbMonth = $plMainWinXML->get_widget('cbMonth');
   $cbMonth->set_active(($cbMonth->get_active + 1)%12);
}
# }}}

# On Button "Previous Month <<"
# {{{
sub prevMonth_onClick {
   my $cbMonth = $plMainWinXML->get_widget('cbMonth');
   $cbMonth->set_active(($cbMonth->get_active - 1)%12);
}
# }}}

# Build a table (Fact or Planed) and fill it in with data
# {{{
sub build_main_table {
        my $cbMonth = $plMainWinXML->get_widget('cbMonth');
        my $cbYear = $plMainWinXML->get_widget('cbYear');
        my $cur_month = $cbMonth->get_active + 1;
        my $cur_year = $cbYear->get_active_text;
        my $cur_page = $pgHolder->get_current_page;
        
        # Padding with 0 ( 09 - September, but 12 - December (without 0))
        $cur_month = "0".$cur_month if (length($cur_month) == 1);
        
        open my $f_planung, "<", $SOURCE_FILE or die "Cannot open ".$SOURCE_FILE." in read mode: $!\n";
        binmode $f_planung, ":utf8";
        my $row = 0;
        my $col = 0;
        if ($cur_page == 0) {           # Page "Fact"
                # Destroy the old table 
                $table_fact->destroy;
                
                # Create a new table
                $table_fact = Gtk2::Table->new($rows,$cols);
        
                foreach (@headersFact) {
                        my $event_box = Gtk2::EventBox->new;
                        my $label = Gtk2::Label->new($_);
                        my $length = length($_);
                        
                        $label->set_alignment(0.5, 1.5);
                        $label->set_justify('center'); 
                        $event_box->add ($label);
                        $label->show;
                        
                        $label->modify_font($font_desc_h);
                        $event_box->modify_bg(normal => $header_color);
                        
                        $label->set_width_chars($length + 5);
                        
                        $table_fact->attach($event_box, $col, $col+1, 0, 1, 'fill', 'fill', 1, 2);
                        
                        $col++; 
                }
                $row++;
                while (<$f_planung>) {
                        next unless m/$cur_month\.$cur_year/;
                        eval $_;
                        die if $@;
                        
                        @DATASET_FACT {@DATASET_KEYS_FACT} = 
                                        ($date, $incRub, $incCom, $isExp, $isCom, $isTotal, $isCCard, $isMBox);
                        $col = 0;
                        foreach my $key (@DATASET_KEYS_FACT) {          
                                my $event_box = Gtk2::EventBox->new;
                                my $label = Gtk2::Label->new($DATASET_FACT{$key});
                                my $length = length($DATASET_FACT{$key});
                                                
                                $label->set_alignment(0.5, 1.5);
                                $label->set_justify('center'); 
                                $event_box->add ($label);
                                $label->show;
                                                                         
                                if ($row == 0) { 
                                        $label->modify_font($font_desc_h);
                                        $event_box->modify_bg (normal => $header_color);
                                } elsif ($row %2 ==0) { 
                                        $event_box->modify_bg (normal => $even_color);
                                }
                                        
                                if ($col == 0) {
                                        $label->set_width_chars($length + 5);
                                }    
                                
                                $table_fact->attach($event_box, $col, $col+1, $row, $row+1,'fill','fill',1,2);
                                         
                                # open dialog "Fact / Is" if clicked
                                $event_box->signal_connect( 'button_release_event', sub {
                                        show_dialog_FactIs('fact', $label->get_text);
                                });
                                        
                                $col++;
                        }
                        $row++;
                }
                $scwin_fact->add_with_viewport( $table_fact );
        }
        elsif ($cur_page == 1) {                # Page "Planed"
                # Destroy the old table 
                $table_plan->destroy;
                
                # Create a new table
                $table_plan = Gtk2::Table->new($rows,$cols);

                foreach (@headersPlaned) {
                my $event_box = Gtk2::EventBox->new;
                my $label = Gtk2::Label->new($_);
                my $length = length($_);
                
                $label->set_alignment(0.5, 1.5);
                $label->set_justify('center'); 
                $event_box->add ($label);
                $label->show;
                
                $label->modify_font($font_desc_h);
                $event_box->modify_bg (normal => $header_color);
                
                $label->set_width_chars($length + 5);
                
                $table_plan->attach($event_box, $col, $col+1, 0, 1, 'fill', 'fill', 1, 2);
                
                $col++; 
                }
                $row++;
                while (<$f_planung>) {
                        next unless m/$cur_month\.$cur_year/;
                        eval $_;
                        die if $@;
                        
                        @DATASET_PLANED {@DATASET_KEYS_PLANED} = 
                                        ($date, $incRub, $incCom, $plExp, $plCom, $plTotal, $plMBox);
                        $col = 0;
                        foreach my $key (@DATASET_KEYS_PLANED) {                
                                my $event_box = Gtk2::EventBox->new;
                                my $label = Gtk2::Label->new($DATASET_PLANED{$key});
                                my $length = length($DATASET_PLANED{$key});
                                                
                                $label->set_alignment(0.5, 1.5);
                                $label->set_justify('center'); 
                                $event_box->add ($label);
                                $label->show;
                                                                         
                                if ($row == 0) { 
                                        $label->modify_font($font_desc_h);
                                        $event_box->modify_bg (normal => $header_color);
                                } elsif ($row %2 ==0) { 
                                        $event_box->modify_bg (normal => $even_color);
                                }
                                        
                                if ($col == 0) {
                                        $label->set_width_chars($length + 5);
                                }    
                                
                                $table_plan->attach($event_box, $col, $col+1, $row, $row+1,'fill','fill',1,2);
                                
                                # open dialog "Fact / Is" if clicked
                                $event_box->signal_connect( 'button_release_event', sub {
                                        show_dialog_FactIs('planed', $label->get_text);
                                });
                                        
                                $col++;
                        }
                        $row++;
                }
                $scwin_plan->add_with_viewport( $table_plan );
        }               
        $plMainWinXML->get_widget('window')->show_all();    
}
# }}}

# Close Main Window
# {{{
sub planung_quit {
   Gtk2->main_quit; 
}
# }}}

# Open dialog "Fact / Is"
# {{{
sub show_dialog_FactIs {
	my ($mode, $date) = @_;
    my $dlgFactIsXML = Gtk2::GladeXML->new('Planung_MainWin.glade', 'dlg_FactIs');
    my $dlgFactIs = $dlgFactIsXML->get_widget('dlg_FactIs');                        
        
    # Select data from file
    select_by_date($date);
        
    ######### Show Tree View
    #get a scrolled window that will host the treeview
    my $sw = $dlgFactIsXML->get_widget('scWindow');
        
    #this is one of the provided base Gtk2::TreeModel classes.
    my $tree_store = Gtk2::TreeStore->new(qw/Glib::String/);
     
    #fill it with data
    foreach my $key (sort keys %expArts) {  
        #the iter is a pointer in the treestore. We use to add data.
		my $iter = $tree_store->append(undef);
            $tree_store->set ($iter,0 => "$key");
                
        foreach my $chld (sort @{ $expArts{$key} }){
            #here we append child iters to the parent iter and add data to those chils iters.
            my $iter_child = $tree_store->append($iter);
                $tree_store->set ($iter_child,0 => "$chld");
            }
        }
        
    #this will create a treeview, specify $tree_store as its model
    my $tree_view = Gtk2::TreeView->new($tree_store);

	#create a Gtk2::TreeViewColumn to add to $tree_view
    my $tree_column = Gtk2::TreeViewColumn->new();
    $tree_column->set_title ("Сортировка");
                        
    #create a renderer that will be used to display info
	#in the model
	my $renderer = Gtk2::CellRendererText->new;
	#add this renderer to $tree_column. This works like a Gtk2::Hbox
	# so you can add more than one renderer to $tree_column                 
    $tree_column->pack_start ($renderer, FALSE);
                
    # set the cell "text" attribute to column 0   
    #- retrieve text from that column in treestore 
    # Thus, the "text" attribute's value will depend on the row's value
    # of column 0 in the model($treestore),
    # and this will be displayed by $renderer,
    # which is a text renderer
    $tree_column->add_attribute($renderer, text => 0);
        
    #add $tree_column to the treeview
    $tree_view->append_column ($tree_column);
        
    # make it searchable
    $tree_view->set_search_column(0);
        
    # Allow sorting on the column
    $tree_column->set_sort_column_id(0);
   
    # Allow drag and drop reordering of rows
	$tree_view->set_reorderable(FALSE);
        
    $sw->add($tree_view);
    $sw->show_all();
    ######### END: Show Tree View
        
    # Fill in income arts
    my $artIncome = $dlgFactIsXML->get_widget('dlgFI_ArtIncome');
    for (my $i=0; $i<@incomeArts; $i++) {
        $artIncome->insert_text($i, $incomeArts[$i]);
    }
        
    # Switch Fields to Read Only
    my $isExp = $dlgFactIsXML->get_widget('dlgFI_IsExp');
    my $isComment = $dlgFactIsXML->get_widget('dlgFI_IsComment');
    my $plExp = $dlgFactIsXML->get_widget('dlgFI_PlanedExp');
    my $plComment = $dlgFactIsXML->get_widget('dlgFI_PlanedComment');
        
    $mode eq 'fact' ? $plExp->set_editable(0) : $isExp->set_editable(0);
        
    #
    $tree_view->signal_connect_after('cursor-changed', sub {
			change_selection_in_tree_veiw($tree_view, $isExp, $plExp);
        });
        
    #
    $isExp->signal_connect('changed', sub {update_dataset_on_change($tree_view, $isExp, $mode);});
    $plExp->signal_connect('value-changed', sub {update_dataset_on_change($tree_view, $plExp, $mode);});

    # TODO: Button "Save"
    my $btnSave = $dlgFactIsXML->get_widget('dlgFI_Save');
	$btnSave->signal_connect('clicked', sub {
			update_by_date($date);
			$dlgFactIs->destroy;
			build_main_table;
		});

                
    # Button "Cancel"
    my $btnCancel = $dlgFactIsXML->get_widget('dlgFI_Cancel');
    $btnCancel->signal_connect('clicked', sub {$dlgFactIs->destroy;});
       
    #$dlgFactIs->signal_connect('response', sub {$dlgFactIs->destroy;});
    $dlgFactIs->run;
    return 1;
}
# }}}

# Get planed and is on changing selection in tree view
# {{{
sub change_selection_in_tree_veiw {
        my ($tree_view, $is_field, $pl_field) = @_;
        my $selected = $tree_view->get_selection;
        
        $selected->selected_foreach( sub{
                my ($model,$path,$iter) = @_;
                        
                #we want data at the model's column 0  
                #where the iter is pointing
                my $value = $model->get($iter,0);
                my $key;
				
				# if it is a child then show it
				unless (exists $expArts{$value}) {
                        foreach my $exp_key (keys %DATASET_FACT_EXP_ARTS) {
                                if ($value eq $DATASET_FACT_EXP_ARTS{$exp_key}) {
                                        $key = $exp_key;
                                        last;
                                }
                        }
                        $is_field->set_text($DATASET{$key});
                        
                        foreach my $exp_key (keys %DATASET_PLANED_EXP_ARTS) {
                                if ($value eq $DATASET_PLANED_EXP_ARTS{$exp_key}) {
                                        $key = $exp_key;
                                        last;
                                }
                        }
                        $pl_field->set_text($DATASET{$key});
                }
				# if it is a parent then show the sum of its children
				else {
					my $sum_fact = 0;
					my $sum_planed = 0;
					my %reversed_fact = reverse %DATASET_FACT_EXP_ARTS;
					my %reversed_planed = reverse %DATASET_PLANED_EXP_ARTS;
					foreach my $chld_element (@{$expArts{$value}}) {
						$sum_fact += $DATASET{$reversed_fact{$chld_element}};
						$sum_planed += $DATASET{$reversed_planed{$chld_element}};
					}
					$is_field->set_text($sum_fact);
					$pl_field->set_text($sum_planed);
				}
        });
}
# }}}

# Hash key of the changed item
# {{{
sub get_changed_item {
        my ($tree_view, $mode) = @_;
        my $selected = $tree_view->get_selection;
        my $key;
        my $value;
        
        $selected->selected_foreach( sub{
                my ($model,$path,$iter) = @_;
                        
                #we want data at the model's column 0  
                #where the iter is pointing
                $value = $model->get($iter,0);
                
                if ($mode eq 'fact') {
                        foreach my $exp_key (keys %DATASET_FACT_EXP_ARTS) {
                                if ($value eq $DATASET_FACT_EXP_ARTS{$exp_key}) {
                                        $key = $exp_key;
                                        last;
                                }
                        }
                }                       
                else {
                        foreach my $exp_key (keys %DATASET_PLANED_EXP_ARTS) {
                                if ($value eq $DATASET_PLANED_EXP_ARTS{$exp_key}) {
                                        $key = $exp_key;
                                        last;
                                }
                        }
                }
        });
        return ($key, $value);
}
# }}}

# Update dataset hash on change event
# {{{
sub update_dataset_on_change {
        my ($tree_view, $field, $mode) = @_;
        my ($expArt, $expArtVal) = get_changed_item($tree_view, $mode);
        
#       $mode eq 'fact' ? $DATASET_FACT_EXP_ARTS{$expArt} = $field->get_text 
#               : $DATASET_PLANED_EXP_ARTS{$expArt} = $field->get_text;
        
        #unless (exists $reversedParents{$expArtVal}) {
                $DATASET{$expArt} = $field->get_text;
                
                # DEBUGGING
                print "TEST> ".$field->get_text."\n" if DEBUG;
        #}      
        return FALSE;
}
# }}}
######### END: subroutines: GLADE-handlers

######### Subroutines: Flat DB

# Select
# {{{
sub select_by_date {
        my $date = shift;
        
        # Check section
        open my $f_planung, "<", $SOURCE_FILE or die "Cannot open ".$SOURCE_FILE." in read mode: $!\n";
                
        # Search dataset in DB file
        while (<$f_planung>) {
                next unless m/$date/;
                eval $_;
                die if $@;
                
                @DATASET {"date", "incRub", "incCom", "plExp", "plCom", "plTotal", "plMBox",
                "isExp", "isCom", "isTotal", "isCCard", "isMBox", "isKidCard", "isFood", "isMisha",
                "isBenzin", "isFoodWork", "isProezd", "isKvarplata", "isProchee", "isProcheeCom",
                "isPivo", "isPodarki", "isCreditS",     "isCreditR", "isCreditRF", "isMobile",
                "isInternet", "isLekarstva", "plFood", "plMisha", "plBenzin", "plFoodWork", "plProezd",
                "plKvarplata", "plProchee",     "plProcheeCom", "plPivo", "plPodarki", "plCreditS",
                "plCreditR", "plCreditRF", "plMobile", "plInternet", "plLekarstva"} =
                ( $date, $incRub, $incCom, $plExp, $plCom, $plTotal, $plMBox, $isExp, $isCom, $isTotal,
                $isCCard, $isMBox, $isKidCard, $isFood, $isMisha, $isBenzin, $isFoodWork, $isProezd, $isKvarplata,
                $isProchee, $isProcheeCom, $isPivo, $isPodarki, $isCreditS,  $isCreditR, $isCreditRF, $isMobile,
                $isInternet, $isLekarstva, $plFood,     $plMisha, $plBenzin, $plFoodWork, $plProezd, $plKvarplata,
                $plProchee, $plProcheeCom, $plPivo, $plPodarki, $plCreditS, $plCreditR, $plCreditRF, $plMobile,
                $plInternet, $plLekarstva);
        }
}
# }}}

# Update
# {{{
sub update_by_date {
    my $par_date = shift;
	my $tmp = "./Data/~TMP_$$";
        
	# Calculate Total Expenses
	my $sum_isExp = 0;
	my $sum_plExp = 0;
	$sum_isExp += $DATASET{$_} foreach (reverse %DATASET_FACT_EXP_ARTS);
	$sum_plExp += $DATASET{$_} foreach (reverse %DATASET_PLANED_EXP_ARTS);
	print "DATASET{isExp} = $DATASET{'isExp'}\n" if DEBUG;
	print "DATASET{plExp} = $DATASET{'plExp'}\n" if DEBUG;
	
	my $delta_isExp = $sum_isExp - $DATASET{'isExp'};
	my $delta_plExp = $sum_plExp - $DATASET{'plExp'};
	
	$DATASET{'isTotal'} -= $delta_isExp;
	$DATASET{'plTotal'} -= $delta_plExp;
	
	$DATASET{'isExp'} = $sum_isExp;
	$DATASET{'plExp'} = $sum_plExp;
	
	print "DATASET{isTotal} = $DATASET{'isTotal'}\n" if DEBUG;
	print "DATASET{plTotal} = $DATASET{'plTotal'}\n" if DEBUG;
		
        # Open files
        open my $f_planung, "<", $SOURCE_FILE or die "Cannot open ".$SOURCE_FILE." in read mode: $!\n";
		open my $f_tmp, ">", $tmp or die "Cannot create/open temporary file in write mode: $!\n";
                
        # Update: write to new file and then rename it
		my $dateAfter = 0;
        while (<$f_planung>) {
			if ($dateAfter == 1) {
				eval $_;
                die if $@;
                
                $isTotal -= $delta_isExp;
				$plTotal -= $delta_plExp;
				
				$_ = Data::Dumper->new( [
					$date, $incRub, $incCom, $plExp, $plCom, $plTotal, $plMBox, $isExp, $isCom, $isTotal,
					$isCCard, $isMBox, $isKidCard, $isFood, $isMisha, $isBenzin, $isFoodWork, $isProezd, $isKvarplata,
					$isProchee, $isProcheeCom, $isPivo, $isPodarki, $isCreditS,  $isCreditR, $isCreditRF, $isMobile,
					$isInternet, $isLekarstva, $plFood, $plMisha, $plBenzin, $plFoodWork, $plProezd, $plKvarplata,
					$plProchee, $plProcheeCom, $plPivo, $plPodarki, $plCreditS, $plCreditR, $plCreditRF, $plMobile,
					$plInternet, $plLekarstva
					], 
					[
					"date", "incRub", "incCom", "plExp", "plCom", "plTotal", "plMBox",
					"isExp", "isCom", "isTotal", "isCCard", "isMBox", "isKidCard", "isFood", "isMisha",
					"isBenzin", "isFoodWork", "isProezd", "isKvarplata", "isProchee", "isProcheeCom",
					"isPivo", "isPodarki", "isCreditS",     "isCreditR", "isCreditRF", "isMobile",
					"isInternet", "isLekarstva", "plFood", "plMisha", "plBenzin", "plFoodWork", "plProezd",
					"plKvarplata", "plProchee",     "plProcheeCom", "plPivo", "plPodarki", "plCreditS",
					"plCreditR", "plCreditRF", "plMobile", "plInternet", "plLekarstva"
					] )->Dump();
				$_ .= "\n";
			}
		
			next unless m/$par_date/;
				
			$dateAfter = 1;
            eval $_;
            die if $@;
                
            ( $par_date, $incRub, $incCom, $plExp, $plCom, $plTotal, $plMBox, $isExp, $isCom, $isTotal,
            $isCCard, $isMBox, $isKidCard, $isFood, $isMisha, $isBenzin, $isFoodWork, $isProezd, $isKvarplata,
            $isProchee, $isProcheeCom, $isPivo, $isPodarki, $isCreditS,  $isCreditR, $isCreditRF, $isMobile,
            $isInternet, $isLekarstva, $plFood, $plMisha, $plBenzin, $plFoodWork, $plProezd, $plKvarplata,
            $plProchee, $plProcheeCom, $plPivo, $plPodarki, $plCreditS, $plCreditR, $plCreditRF, $plMobile,
            $plInternet, $plLekarstva) = @DATASET {"date", "incRub", "incCom", "plExp", "plCom", "plTotal", "plMBox",
            "isExp", "isCom", "isTotal", "isCCard", "isMBox", "isKidCard", "isFood", "isMisha",
            "isBenzin", "isFoodWork", "isProezd", "isKvarplata", "isProchee", "isProcheeCom",
            "isPivo", "isPodarki", "isCreditS",     "isCreditR", "isCreditRF", "isMobile",
            "isInternet", "isLekarstva", "plFood", "plMisha", "plBenzin", "plFoodWork", "plProezd",
            "plKvarplata", "plProchee",     "plProcheeCom", "plPivo", "plPodarki", "plCreditS",
            "plCreditR", "plCreditRF", "plMobile", "plInternet", "plLekarstva"};
								
			$_ = Data::Dumper->new( [
				$date, $incRub, $incCom, $plExp, $plCom, $plTotal, $plMBox, $isExp, $isCom, $isTotal,
				$isCCard, $isMBox, $isKidCard, $isFood, $isMisha, $isBenzin, $isFoodWork, $isProezd, $isKvarplata,
				$isProchee, $isProcheeCom, $isPivo, $isPodarki, $isCreditS,  $isCreditR, $isCreditRF, $isMobile,
				$isInternet, $isLekarstva, $plFood,     $plMisha, $plBenzin, $plFoodWork, $plProezd, $plKvarplata,
				$plProchee, $plProcheeCom, $plPivo, $plPodarki, $plCreditS, $plCreditR, $plCreditRF, $plMobile,
				$plInternet, $plLekarstva
				], 
				[
				"date", "incRub", "incCom", "plExp", "plCom", "plTotal", "plMBox",
				"isExp", "isCom", "isTotal", "isCCard", "isMBox", "isKidCard", "isFood", "isMisha",
				"isBenzin", "isFoodWork", "isProezd", "isKvarplata", "isProchee", "isProcheeCom",
				"isPivo", "isPodarki", "isCreditS",     "isCreditR", "isCreditRF", "isMobile",
				"isInternet", "isLekarstva", "plFood", "plMisha", "plBenzin", "plFoodWork", "plProezd",
				"plKvarplata", "plProchee",     "plProcheeCom", "plPivo", "plPodarki", "plCreditS",
				"plCreditR", "plCreditRF", "plMobile", "plInternet", "plLekarstva"
				] )->Dump();
			$_ .= "\n";
		}
		continue {
			# Write data in tmp file
			print {$f_tmp} $_ or die "Error writing $tmp: $!\n";
		}
		close $f_planung or die "Error while closing file ".$SOURCE_FILE.": $!\n";
		close $f_tmp or die "Error while closing file ".$tmp.": $!\n";
		unlink $SOURCE_FILE or die "Unable to delete origin file ".$SOURCE_FILE.": $!\n";
		rename $tmp, $SOURCE_FILE or die "Unable to rename file ".$tmp.": $!\n";	
}
# }}}

# Insert
# {{{
sub insert_entry {
        my $date = shift;
        
        # Check section
        #die "Insert into DB has failed: not all parameters.\n" unless @_ == 46;
        open my $f_planung, ">>", $SOURCE_FILE or die "Cannot open ".$SOURCE_FILE." in read mode: $!\n";
                
        my $dumper = Data::Dumper->new([@DATASET {
                "date", "incRub", "incCom", "plExp", "plCom", "plTotal", "plMBox",
                "isExp", "isCom", "isTotal", "isCCard", "isMBox", "isKidCard", "isFood", "isMisha",
                "isBenzin", "isFoodWork", "isProezd", "isKvarplata", "isProchee", "isProcheeCom",
                "isPivo", "isPodarki", "isCreditS",     "isCreditR", "isCreditRF", "isMobile",
                "isInternet", "isLekarstva", "plFood", "plMisha", "plBenzin", "plFoodWork", "plProezd",
                "plKvarplata", "plProchee",     "plProcheeCom", "plPivo", "plPodarki", "plCreditS",
                "plCreditR", "plCreditRF", "plMobile", "plInternet", "plLekarstva"
                }],
                [$date, $incRub,        $incCom, $plExp, $plCom, $plTotal, $plMBox,     $isExp, $isCom, $isTotal,
                $isCCard, $isMBox, $isKidCard, $isFood, $isMisha, $isBenzin, $isFoodWork, $isProezd, $isKvarplata,
                $isProchee,     $isProcheeCom, $isPivo, $isPodarki,     $isCreditS,     $isCreditR,     $isCreditRF, $isMobile,
                $isInternet, $isLekarstva, $plFood,     $plMisha, $plBenzin, $plFoodWork, $plProezd, $plKvarplata,
                $plProchee,     $plProcheeCom, $plPivo, $plPodarki,     $plCreditS,     $plCreditR,     $plCreditRF, $plMobile,
                $plInternet, $plLekarstva]);
        my $dumpedValues = $dumper->Dump();
        print $f_planung "$dumpedValues\n";
}
# }}}
######### END: subroutines: Flat DB